package com.yilin.tms.order.service.payment.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yilin.commons.exception.BusinessException;
import com.yilin.commons.util.ArrayUtil;
import com.yilin.commons.util.DateTimeUtil;
import com.yilin.commons.util.MathUtil;
import com.yilin.tms.core.application.PageData;
import com.yilin.tms.core.commons.utils.QueryUtil;
import com.yilin.tms.core.entity.capital.TradeRecord;
import com.yilin.tms.core.entity.order.goods.GoodsOrder;
import com.yilin.tms.core.entity.order.payment.OrderPaymentCost;
import com.yilin.tms.core.entity.order.payment.OrderRefundCost;
import com.yilin.tms.core.entity.order.rob.RobOrder;
import com.yilin.tms.core.entity.order.transit.TransitOrder;
import com.yilin.tms.core.entity.user.RoleType;
import com.yilin.tms.core.entity.user.UserType;
import com.yilin.tms.core.entity.user.account.Account;
import com.yilin.tms.order.mapper.payment.OrderRefundCostMapper;
import com.yilin.tms.order.service.payment.IOrderPaymentCostService;
import com.yilin.tms.order.service.payment.IOrderRefundCostService;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.transaction.Transactional;
import java.util.Date;
import java.util.List;

@Service
@Transactional
public class OrderRefundCostService extends ServiceImpl<OrderRefundCostMapper, OrderRefundCost> implements IOrderRefundCostService {

    @Resource
    private OrderRefundCostMapper orderRefundCostMapper;
    @Resource
    private IOrderPaymentCostService orderPaymentService;

    /**
     * 通知支付结果，重复通知无效
     * 通知结果只更新状态
     */
    @Override
    public void updateOrderRefundResult(Account loginUser, TradeRecord tradeRecord) {
        List<TradeRecord.TradeStatus> statusList = ArrayUtil.initList(TradeRecord.TradeStatus.paySuccess, TradeRecord.TradeStatus.payFail, TradeRecord.TradeStatus.wait, TradeRecord.TradeStatus.create, TradeRecord.TradeStatus.close);
        if (!statusList.contains(tradeRecord.getTradeStatus())) throw new BusinessException("支付结果状态有误！");
        String[] orderPaymentIds = tradeRecord.getOrderPaymentIds().split(",");
        List<OrderRefundCost> refundCostList = getOrderRefundListByIds(ArrayUtil.initList(orderPaymentIds));
        refundCostList.forEach(orderRefundCost -> {
            if (orderRefundCost.getRefundStatus() == OrderRefundCost.RefundStatus.success) throw new BusinessException("订单已经支付完成...");
            /// 分别在成功，创建，关闭+失败时更新状态
            orderRefundCost.setTradeNo(tradeRecord.getTradeNo());
            if (tradeRecord.getTradeStatus() == TradeRecord.TradeStatus.paySuccess) {
                orderRefundCost.setRefundStatus(OrderRefundCost.RefundStatus.success);
                orderRefundCost.setRefundType(tradeRecord.getPayType());
                orderRefundCost.setOptUserId(tradeRecord.getOptUserId());
                orderRefundCost.setOptUserName(tradeRecord.getOptUserName());
                orderRefundCost.setBankFlowNo(tradeRecord.getBankFlowNo());
                orderRefundCost.setPaymentTypeName(tradeRecord.getPayType().name+tradeRecord.getBankType().name);
                orderRefundCost.setPaymentCapitalAccount(tradeRecord.getPaymentCapitalAccount());
                orderRefundCost.setIncomeCapitalAccount(tradeRecord.getIncomeCapitalAccount());
                orderRefundCost.setRefundCompleteTime(tradeRecord.getFinishTime());
            } else if (tradeRecord.getTradeStatus() == TradeRecord.TradeStatus.wait || tradeRecord.getTradeStatus() == TradeRecord.TradeStatus.create) {
                orderRefundCost.setRefundStatus(OrderRefundCost.RefundStatus.wait);
                orderRefundCost.setInitiateUserId(loginUser == null ? null : loginUser.getId());
                orderRefundCost.setInitiateUserName(loginUser == null ? null : loginUser.getName());
            } else {//失败/关闭时，恢复预支付单状态
                orderRefundCost.setRefundStatus(OrderRefundCost.RefundStatus.fail);
                orderRefundCost.setTradeNo(null);
            }
            orderRefundCostMapper.updateById(orderRefundCost);
        });
    }

    /**
     * 货单退款 01
     */
    @Override
    public void generateGoodsOrderRefund(GoodsOrder goodsOrder) {
        OrderPaymentCost orderPaymentCost = orderPaymentService.getOrderPaymentByGoodsOrderId(goodsOrder.getId());
        //计算退款额度，已装载无法退款
        if (orderPaymentCost.getPayCost() > 0 && orderPaymentCost.getPayStatus() == OrderPaymentCost.PayStatus.complete) {
            Double surplusMeasure = MathUtil.subtract(goodsOrder.getShipperTotalMeasure(), goodsOrder.getEmbarkMeasure());
            double refundRatio = MathUtil.divide(surplusMeasure, goodsOrder.getShipperTotalMeasure(), 3);
            OrderRefundCost orderRefundCost = getOrderRefundCostByPaymentRatio(orderPaymentCost, refundRatio);
            generateOrderRefund(orderPaymentCost, orderRefundCost);
        }
    }

    /**
     * 抢单退款 02
     */
    @Override
    public void generateRobOrderRefund(RobOrder robOrder, GoodsOrder goodsOrder) {
        OrderPaymentCost orderPaymentCost = orderPaymentService.getOrderPaymentByRobOrderId(robOrder.getId());
        //抢单默认全部退款
        if (orderPaymentCost.getPayCost() > 0 && orderPaymentCost.getPayStatus() == OrderPaymentCost.PayStatus.complete) {
            OrderRefundCost orderRefundCost = getOrderRefundCostByPaymentRatio(orderPaymentCost, 1.0);
            generateOrderRefund(orderPaymentCost, orderRefundCost);
        }
        //如果货单已作废或已删除，货单也要按比例进行退款
        if (goodsOrder.getGoodsStatus() == GoodsOrder.GoodsStatus.scrap) {
            OrderPaymentCost goodsPaymentCost = orderPaymentService.getOrderPaymentByGoodsOrderId(goodsOrder.getId());
            if (goodsPaymentCost.getPayCost() > 0 && goodsPaymentCost.getPayStatus() == OrderPaymentCost.PayStatus.complete) {
                double refundRatio = MathUtil.divide(robOrder.getRobMeasure(), goodsOrder.getShipperTotalMeasure(), 3);
                OrderRefundCost goodsRefundCost = getOrderRefundCostByPaymentRatio(goodsPaymentCost, refundRatio);
                generateOrderRefund(goodsPaymentCost, goodsRefundCost);
            }
        }
    }

    /**
     * 运单退款 03
     */
    @Override
    public void generateTransitOrderRefund(TransitOrder transitOrder, RobOrder robOrder, GoodsOrder goodsOrder) {
        //默认运单全退
        List<OrderPaymentCost> orderPaymentList = orderPaymentService.getOrderPaymentListByTransitOrderId(transitOrder.getId());
        for (OrderPaymentCost orderPaymentCost : orderPaymentList) {
            if (orderPaymentCost.getPayCost() > 0 && orderPaymentCost.getPayStatus() == OrderPaymentCost.PayStatus.complete) {
                OrderRefundCost orderRefundCost = getOrderRefundCostByPaymentRatio(orderPaymentCost, 1.0);
                generateOrderRefund(orderPaymentCost, orderRefundCost);
            }
        }
        //抢单按运单分配比列退款
        OrderPaymentCost robPaymentCost = orderPaymentService.getOrderPaymentByRobOrderId(robOrder.getId());
        if (robPaymentCost.getPayCost() > 0 && robPaymentCost.getPayStatus() == OrderPaymentCost.PayStatus.complete) {
            double refundRatio = MathUtil.divide(transitOrder.getAssignMeasure(), robOrder.getRobMeasure(), 3);
            OrderRefundCost orderRefundCost = getOrderRefundCostByPaymentRatio(robPaymentCost, refundRatio);
            generateOrderRefund(robPaymentCost, orderRefundCost);
        }
        //运单作废无法恢复货单，货单也要按运单比例进行退款
        OrderPaymentCost goodsPaymentCost = orderPaymentService.getOrderPaymentByGoodsOrderId(goodsOrder.getId());
        if (goodsPaymentCost.getPayCost() > 0 && goodsPaymentCost.getPayStatus() == OrderPaymentCost.PayStatus.complete) {
            double refundRatio = MathUtil.divide(transitOrder.getAssignMeasure(), goodsOrder.getShipperTotalMeasure(), 3);
            OrderRefundCost goodsRefundCost = getOrderRefundCostByPaymentRatio(goodsPaymentCost, refundRatio);
            generateOrderRefund(goodsPaymentCost, goodsRefundCost);
        }
    }

    /**
     * 根据比例生成退款单
     */
    private OrderRefundCost getOrderRefundCostByPaymentRatio(OrderPaymentCost orderPaymentCost, double refundRatio) {
        OrderRefundCost goodsRefundCost = new OrderRefundCost();
        ///--理论上退款费用
        goodsRefundCost.setShouldInsuranceCost(MathUtil.multiply(orderPaymentCost.getPayInsuranceCost(), refundRatio,2));
        goodsRefundCost.setShouldAdditionalCost(MathUtil.multiply(orderPaymentCost.getPayAdditionalCost(), refundRatio,2));
        goodsRefundCost.setShouldTransportCost(MathUtil.multiply(orderPaymentCost.getPayTransportCost(), refundRatio,2));
        goodsRefundCost.setShouldTaxCost(MathUtil.multiply(orderPaymentCost.getPayTaxCost(), refundRatio,2));
        goodsRefundCost.setShouldShipperFeeCost(MathUtil.multiply(orderPaymentCost.getPayShipperFeeCost(), refundRatio,2));
        goodsRefundCost.setShouldPayCost(MathUtil.multiply(orderPaymentCost.getPayCost(), refundRatio,2));
        ///--实际退款费用
        goodsRefundCost.setRefundInsuranceCost(MathUtil.multiply(orderPaymentCost.getPayInsuranceCost(), refundRatio,2));
        goodsRefundCost.setRefundAdditionalCost(MathUtil.multiply(orderPaymentCost.getPayAdditionalCost(), refundRatio,2));
        goodsRefundCost.setRefundTransportCost(MathUtil.multiply(orderPaymentCost.getPayTransportCost(), refundRatio,2));
        goodsRefundCost.setRefundTaxCost(MathUtil.multiply(orderPaymentCost.getPayTaxCost(), refundRatio,2));
        goodsRefundCost.setRefundShipperFeeCost(MathUtil.multiply(orderPaymentCost.getPayShipperFeeCost(), refundRatio,2));
        goodsRefundCost.setRefundCost(MathUtil.multiply(orderPaymentCost.getPayCost(), refundRatio,2));
        return goodsRefundCost;
    }

    /**
     * 生成退款单
     * 提供原支付单+退还费用详细
     * 直接退款 直接此方法 只退款传入支付单
     */
    @Override
    public OrderRefundCost generateOrderRefund(OrderPaymentCost orderPaymentCost, OrderRefundCost orderRefundCost) {
        List<OrderRefundCost> refundCostList = getOrderRefundCostListByPaymentId(orderPaymentCost.getId());
        Double refundedCost = ArrayUtil.numListAdd(refundCostList, OrderRefundCost::getRefundCost);
        if (orderRefundCost.getRefundCost() > MathUtil.subtract(orderPaymentCost.getPayCost(), refundedCost)) {
            throw new BusinessException("付款订单金额退还超限！");
        }
        //原始费用
        orderRefundCost.setOriginalInsuranceCost(orderPaymentCost.getSplitInsuranceCost());
        orderRefundCost.setOriginalAdditionalCost(orderPaymentCost.getSplitAdditionalCost());
        orderRefundCost.setOriginalTransportCost(orderPaymentCost.getTransportCost());
        orderRefundCost.setOriginalTaxCost(orderPaymentCost.getTaxCost());
        orderRefundCost.setOriginalShipperFeeCost(orderPaymentCost.getShipperFeeCost());
        orderRefundCost.setOriginalPayCost(orderPaymentCost.getPayCost());
        //原始订单信息
        orderRefundCost.setOriginalPaymentId(orderPaymentCost.getId());
        orderRefundCost.setOriginalTradeNo(orderPaymentCost.getTradeNo());
        orderRefundCost.setOriginalBankFlowNo(orderPaymentCost.getBankFlowNo());
        orderRefundCost.setOriginalPaymentCapitalAccount(orderPaymentCost.getPaymentCapitalAccount());
        orderRefundCost.setOriginalIncomeCapitalAccount(orderPaymentCost.getIncomeCapitalAccount());
        orderRefundCost.setOriginalPayStatus(orderPaymentCost.getPayStatus());
        orderRefundCost.setRefundCreateTime(new Date());
        orderRefundCost.setPaymentCapitalAccount(orderRefundCost.getOriginalIncomeCapitalAccount());
        orderRefundCost.setIncomeCapitalAccount(orderRefundCost.getOriginalPaymentCapitalAccount());
        orderRefundCost.setRefundType(orderPaymentCost.getPayType());
        //货主信息
        orderRefundCost.setShipperAccountId(orderPaymentCost.getShipperAccountId());
        orderRefundCost.setShipperAccountName(orderPaymentCost.getShipperAccountName());
        orderRefundCost.setShipperOrganizeId(orderPaymentCost.getShipperOrganizeId());
        orderRefundCost.setShipperOrganizeName(orderPaymentCost.getShipperOrganizeName());
        orderRefundCost.setPrePaymentNo(DateTimeUtil.dateNo("TF"));
        //平台信息
//        orderRefundCost.setPlatId(orderPaymentCost.getPlatId());
//        orderRefundCost.setPlatName(orderPaymentCost.getPlatName());
//        orderRefundCost.setZonePlatId(orderPaymentCost.getZonePlatId());
//        orderRefundCost.setZonePlatName(orderPaymentCost.getZonePlatName());
        //等待中
        orderRefundCost.setRefundStatus(OrderRefundCost.RefundStatus.verify);
        orderRefundCostMapper.insert(orderRefundCost);
        return orderRefundCost;
    }

    /**
     * 锁定退款单
     */
    @Override
    public void lockOrderRefund(Account loginUser, String formRefundId, boolean locking) {
        OrderRefundCost orderRefundCost = orderRefundCostMapper.selectById(formRefundId);
        if (orderRefundCost == null) throw new BusinessException("退款单不存在");
        if (locking && orderRefundCost.getVerifyUserId() != null) throw new BusinessException("订单已锁定");
        if (orderRefundCost.getVerifyUserId() != null && !loginUser.getId().equals(orderRefundCost.getVerifyUserId())) {
            throw new BusinessException("该条记录已被其他用户审核锁定！");
        }
        orderRefundCost.setVerifyUserId(locking ? loginUser.getId() : null);
        orderRefundCost.setVerifyUserName(locking ? loginUser.getName() : null);
        orderRefundCost.setLockTime(locking ? new Date() : null);
        orderRefundCostMapper.updateById(orderRefundCost);
    }

    /**
     * 更新退款单
     */
    @Override
    public void updateOrderRefund(Account loginUser, OrderRefundCost formRefund) {
        OrderRefundCost orderRefundCost = orderRefundCostMapper.selectById(formRefund.getId());
        if (orderRefundCost == null) throw new BusinessException("原始清算记录不存在");
        if (orderRefundCost.getRefundStatus() != OrderRefundCost.RefundStatus.verify)
            throw new BusinessException("退款状态不支持更新");
        if (orderRefundCost.getVerifyUserId() == null) throw new BusinessException("请先锁定记录");
        if (!orderRefundCost.getVerifyUserId().equals(loginUser.getId()))
            throw new BusinessException("该记录正在被其他人操作");
        //实际退款费用
        orderRefundCost.setRefundInsuranceCost(formRefund.getRefundInsuranceCost());
        orderRefundCost.setRefundAdditionalCost(formRefund.getRefundAdditionalCost());
        orderRefundCost.setRefundTransportCost(formRefund.getRefundTransportCost());
        orderRefundCost.setRefundTaxCost(formRefund.getRefundTaxCost());
        orderRefundCost.setRefundShipperFeeCost(formRefund.getRefundShipperFeeCost());
        orderRefundCost.setRefundCost(formRefund.getRefundCost());
        orderRefundCostMapper.updateById(orderRefundCost);
    }

    /**
     * 确认退款单 审核 核定
     */
    @Override
    public void sureOrderRefund(Account loginUser, OrderRefundCost formRefund) {
        updateOrderRefund(loginUser, formRefund);
        OrderRefundCost orderRefundCost = orderRefundCostMapper.selectById(formRefund.getId());
        orderRefundCost.setRefundStatus(OrderRefundCost.RefundStatus.approved);
        orderRefundCostMapper.updateById(orderRefundCost);
    }

    @Override
    public List<OrderRefundCost> getOrderRefundCostListByPaymentId(String paymentId) {
        QueryWrapper<OrderRefundCost> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("original_payment_id", paymentId);
        return orderRefundCostMapper.selectList(queryWrapper);
    }

    @Override
    public List<OrderRefundCost> getOrderRefundListByIds(List<String> orderRefundCostIds) {
        return orderRefundCostMapper.selectBatchIds(orderRefundCostIds);
    }

    @Override
    public OrderRefundCost getOrderRefundById(String orderRefundCostId) {
        return orderRefundCostMapper.selectById(orderRefundCostId);
    }

    @Override
    public PageData<OrderRefundCost> getOrderRefundPage(OrderRefundCost query, Account loginUser, Integer page, Integer limit) {
        QueryWrapper<OrderRefundCost> queryWrapper = new QueryWrapper<>();
//        if (loginUser.getUserType() != UserType.adminUser && loginUser.getUserType() != UserType.yilinUser) {
//            if (loginUser.getUserType() == UserType.zoneUser) {
//                queryWrapper.eq("zone_plat_id", loginUser.getOrganizeId());
//            } else if (loginUser.getUserType() == UserType.platformUser) {
//                queryWrapper.eq("plat_id", loginUser.getOrganizeId());
//            } else {
//                if (loginUser.getRoleType() == RoleType.manager)
//                    queryWrapper.eq("shipper_organize_id", loginUser.getOrganizeId());
//                else queryWrapper.eq("shipper_account_id", loginUser.getId());
//            }
//        }
        return orderRefundCostMapper.selectPage(new PageData<>(page, limit), QueryUtil.andQueryWrapper(queryWrapper, query));
    }


}
